package main

import (
	"fmt"
	log "github.com/sirupsen/logrus"
	"io"
	"os"
)

/*
	初始化日志设置
*/
func init() {
	console := log.New()
	console.SetFormatter(&log.TextFormatter{
		ForceColors:     true,
		FullTimestamp:   true,
		TimestampFormat: "2006-01-02 15:04:05",
	})
	//console.SetOutput(os.Stdout)
	inputfile := log.New()
	inputfile.SetFormatter(&log.TextFormatter{
		FullTimestamp:   true,
		TimestampFormat: "2006-01-02 15:04:05",
	})
	logfile, err := os.OpenFile("./info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		log.Error("打开文件失败")
		return
	}
	log.SetOutput(io.MultiWriter(logfile, os.Stdout))
	log.SetLevel(log.InfoLevel)
	log.SetReportCaller(true)
}

/*
	采用结构体和方法编写一个学生管理系统
		1、学生信息包含: 姓名、年龄、课程(包含两门课程以上)
		2、实现学生的增删改查操作
		3、将学生的信息保存到本地的文件中(data_sts.txt)
*/
func getInput() {
	fmt.Println(`
		学生管理系统
		1、查看全部学生信息
		2、查看单个学生信息
		3、增加学生信息
		4、修改学生信息
		5、删除学生信息
		6、退出系统
	`)
}
func getInputMsg() *Students {
	var (
		Id      int
		Name    string
		Age     int
		Classes []string
	)
	fmt.Println("输入学生ID")
	log.Info("输入学生ID: ", Id)
	fmt.Scan(&Id)
	fmt.Println("输入学生姓名")
	log.Info("输入学生姓名: ", Name)
	fmt.Scan(&Name)
	fmt.Println("输入学生年龄")
	log.Info("输入学生年龄: ", Age)
	fmt.Scan(&Age)
	fmt.Println("输入学生的课程")
	log.Info("输入学生课程: ", Classes)
	for {
		var Class string
		fmt.Scan(&Class)
		if Class == "exit" {
			log.Info("输出课程结束")
			break
		}
		Classes = append(Classes, Class)
		log.Info("多个课程已成功追加到切片Classes: ", Classes)
	}
	stuMgs := NewStudent(Id, Name, Age, Classes)
	return stuMgs //stuMgs 等价于--->NewStudent  这个是Student结构体的构造函数，且返回值就是Student结构体
}
func main() {
	stsMgr := NewStuMgr("./data_file.json") //将存储学生信息的结构体经过构造函数初始化后，开始使用，存储学生信息
	stsMgr.LoadFile()
	for {
		//打印功能
		getInput()
		var choice int
		fmt.Println("输入你的选择")
		log.Info("输入你的选择", choice)
		fmt.Scan(&choice)
		switch choice {
		//查看所有学生信息
		case 1:
			/*
				Viewallsts是构造函数NewStuMgr的一种方法,且这个构造函数NewStuMgr的返回值是stsMgr，因此采用stsMgr.Viewallsts()形式
					来查看保存在这个构造函数中的学生信息
			*/
			//fmt.Println("查看全部学生的信息")
			log.Info("查看全部学生的信息")
			stsMgr.Viewallsts()

			//查看单个学生信息
		case 2:
			/*
					Viewoncests也是学生管理器的构造函数NewStuMgr的一种方法,就是之前讲的方法和接收者的示例。查看单个学生的信息，采用传参的方法
				将学生的id传进去,且这个函数有一个bool类型的返回值,可以通过判断该类型的返回值,确认函数是否执行成功
			*/
			fmt.Println("输入要查询的学生id")
			var stsid int
			fmt.Scan(&stsid)
			log.Info("输入要查询的学生id: ", stsid)
			stsMgr.Viewoncests(stsid)
			//增加学生信息
		case 3:
			/*
					AddMsgsts函数也是构造函数NewStuMgr的一种方法,增加学生信息,调用输入学生信息的函数getInputMsg,且该函数有一个指针类型的结构体返回值
				返回的就是学生结构体中的信息。执行增加学生信息函数时需要将函数getInputMsg的返回值传递进去,并将最后的信息结果保存到构造函数的
				返回值allSts: make([]map[string]*Students, 1024)中,这个也就是等价于在全局变量定义的一个key为string类型,值为*Student类型的切片
			*/
			fmt.Println("增加学生信息")
			log.Info("增加学生信息")
			stuMgs := getInputMsg()
			if ok := stsMgr.AddMsgsts(stuMgs); ok {
				//fmt.Println("增加成功")
				log.Info("增加成功")
			} else {
				//fmt.Println("增加失败")
				log.Error("增加失败")
			}
			//修改学生信息
		case 4:
			/*
					UpdateMsgsts函数也是构造函数NewStuMgr的一种方法,修改学生的信息,通过传参的方法将想要修改学生信息的id传递给更新函数,同时也将输入信息的函数getInputMsg
				也传递给更新函数,当id存在时,更新id对应的信息
			*/
			fmt.Println("输入要修改的学生id")
			var stsid int
			fmt.Scan(&stsid)
			log.Info("输入要修改的学生id: ", stsid)
			stuMgs := getInputMsg()
			if ok := stsMgr.UpdateMsgsts(stsid, stuMgs); ok {
				//fmt.Println("修改成功")
				log.Info("修改成功")
			} else {
				//fmt.Println("修改失败")
				log.Error("修改失败")
			}
			//删除学生信息
		case 5:
			/*
				DelMsgsts函数也是构造函数NewStuMgr的一种方法,删除学生信息,通过传参的方法将想要修改学生信息的id传递给删除函数,当id存在时,执行删除操作
			*/
			fmt.Println("输入要删除的学生id")
			var stsid int
			fmt.Scan(&stsid)
			log.Info("输入要删除的学生id: ", stsid)
			if ok := stsMgr.DelMsgsts(stsid); ok {
				//fmt.Println("删除成功")
				log.Info("删除成功")
			} else {
				//fmt.Println("删除失败")
				log.Error("删除失败")
			}
		case 6:
			//fmt.Println("退出系统~~~")
			log.Info("退出系统")
			os.Exit(10002)
		default:
			//fmt.Println("输入有误!!!")
			log.Error("输入有误!!!")
			break
		}
	}
}
